﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Security.Principal;
using System.Web;

namespace NWebMock
{
    public class HttpApplicationWrapper : IHttpApplication
    {
        #region Constructors

        public HttpApplicationWrapper(HttpApplication application, IHttpContext context)
        {
            if (application == null)
            {
                throw new ArgumentNullException("application");
            }
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            this.innerApplication = application;
            this.innerContext = context;

            application.Disposed += new EventHandler(OnDisposed);
        }

        #endregion

        #region Fields

        private HttpApplication innerApplication = null;
        private IHttpApplicationState innerApplicationState = null;
        private IHttpContext innerContext = null;
        private IHttpModuleCollection innerModules = null;

        #endregion

        #region Properties

        public IHttpApplicationState Application
        {
            get
            {
                if (this.innerApplicationState != null)
                {
                    return this.innerApplicationState;
                }

                if (this.innerApplication.Application != null)
                {
                    this.innerApplicationState = new HttpApplicationStateWrapper(this.innerApplication.Application);
                }

                return this.innerApplicationState;
            }
        }

        public IHttpContext Context { get { return this.innerContext; } }

        public IHttpModuleCollection Modules
        {
            get
            {
                if (this.innerModules != null)
                {
                    return this.innerModules;
                }

                if (this.innerApplication.Modules != null)
                {
                    this.innerModules = new HttpModuleCollectionWrapper(this.innerApplication.Modules);
                }

                return this.innerModules;
            }
        }

        public IHttpRequest Request { get { return this.innerContext.Request; } }

        public IHttpResponse Response { get { return this.innerContext.Response; } }

        public IHttpServerUtility Server { get { return this.innerContext.Server; } }

        public IHttpSessionState Session { get { return this.innerContext.Session; } }

        public ISite Site { get { return this.innerApplication.Site; } set { this.innerApplication.Site = value; } }

        public IPrincipal User { get { return this.innerApplication.User; } }

        #endregion

        #region Methods

        public void AddOnAcquireRequestStateAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnAcquireRequestStateAsync(bh, eh);
        }

        public void AddOnAcquireRequestStateAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnAcquireRequestStateAsync(bh, eh, state);
        }

        public void AddOnAuthenticateRequestAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnAuthenticateRequestAsync(bh, eh);
        }

        public void AddOnAuthenticateRequestAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnAuthenticateRequestAsync(bh, eh, state);
        }

        public void AddOnAuthorizeRequestAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnAuthorizeRequestAsync(bh, eh);
        }

        public void AddOnAuthorizeRequestAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnAuthorizeRequestAsync(bh, eh, state);
        }

        public void AddOnEndRequestAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnEndRequestAsync(bh, eh);
        }

        public void AddOnEndRequestAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnEndRequestAsync(bh, eh, state);
        }

        public void AddOnLogRequestAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnLogRequestAsync(bh, eh);
        }

        public void AddOnLogRequestAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnLogRequestAsync(bh, eh, state);
        }

        public void AddOnMapRequestHandlerAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnMapRequestHandlerAsync(bh, eh);
        }

        public void AddOnMapRequestHandlerAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnMapRequestHandlerAsync(bh, eh, state);
        }

        public void AddOnPostAcquireRequestStateAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnPostAcquireRequestStateAsync(bh, eh);
        }

        public void AddOnPostAcquireRequestStateAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnPostAcquireRequestStateAsync(bh, eh, state);
        }

        public void AddOnPostAuthenticateRequestAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnPostAuthenticateRequestAsync(bh, eh);
        }

        public void AddOnPostAuthenticateRequestAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnPostAuthenticateRequestAsync(bh, eh, state);
        }

        public void AddOnPostAuthorizeRequestAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnPostAuthorizeRequestAsync(bh, eh);
        }

        public void AddOnPostAuthorizeRequestAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnPostAuthorizeRequestAsync(bh, eh, state);
        }

        public void AddOnPostLogRequestAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnPostLogRequestAsync(bh, eh);
        }

        public void AddOnPostLogRequestAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnPostLogRequestAsync(bh, eh, state);
        }

        public void AddOnPostMapRequestHandlerAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnPostMapRequestHandlerAsync(bh, eh);
        }

        public void AddOnPostMapRequestHandlerAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnPostMapRequestHandlerAsync(bh, eh, state);
        }

        public void AddOnPostReleaseRequestStateAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnPostReleaseRequestStateAsync(bh, eh);
        }

        public void AddOnPostReleaseRequestStateAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnPostReleaseRequestStateAsync(bh, eh, state);
        }

        public void AddOnPostRequestHandlerExecuteAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnPostRequestHandlerExecuteAsync(bh, eh);
        }

        public void AddOnPostRequestHandlerExecuteAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnPostRequestHandlerExecuteAsync(bh, eh, state);
        }

        public void AddOnPostResolveRequestCacheAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnPostResolveRequestCacheAsync(bh, eh);
        }

        public void AddOnPostResolveRequestCacheAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnPostResolveRequestCacheAsync(bh, eh, state);
        }

        public void AddOnPostUpdateRequestCacheAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnPostUpdateRequestCacheAsync(bh, eh);
        }

        public void AddOnPostUpdateRequestCacheAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnPostUpdateRequestCacheAsync(bh, eh, state);
        }

        public void AddOnPreRequestHandlerExecuteAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnPreRequestHandlerExecuteAsync(bh, eh);
        }

        public void AddOnPreRequestHandlerExecuteAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnPreRequestHandlerExecuteAsync(bh, eh, state);
        }

        public void AddOnReleaseRequestStateAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnReleaseRequestStateAsync(bh, eh);
        }

        public void AddOnReleaseRequestStateAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnReleaseRequestStateAsync(bh, eh, state);
        }

        public void AddOnResolveRequestCacheAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnResolveRequestCacheAsync(bh, eh);
        }

        public void AddOnResolveRequestCacheAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnResolveRequestCacheAsync(bh, eh, state);
        }

        public void AddOnUpdateRequestCacheAsync(BeginEventHandler bh, EndEventHandler eh)
        {
            this.innerApplication.AddOnUpdateRequestCacheAsync(bh, eh);
        }

        public void AddOnUpdateRequestCacheAsync(BeginEventHandler bh, EndEventHandler eh, object state)
        {
            this.innerApplication.AddOnUpdateRequestCacheAsync(bh, eh, state);
        }

        public void CompleteRequest()
        {
            this.innerApplication.CompleteRequest();
        }

        public void Dispose()
        {
            this.innerApplication.Dispose();
        }

        public string GetVaryByCustomString(HttpContext context, string custom)
        {
            return this.innerApplication.GetVaryByCustomString(context, custom);
        }

        public void Init()
        {
            this.innerApplication.Init();
        }

        protected void OnDisposed(object sender, EventArgs e)
        {
            if (this.Disposed != null)
            {
                this.Disposed(this, e);
            }
        }

        #endregion

        #region Events

        public event EventHandler Disposed;

        #endregion

        #region IHttpAsyncHandler Members

        IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
        {
            return ((IHttpAsyncHandler)this.innerApplication).BeginProcessRequest(context, cb, extraData);
        }

        void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
        {
            ((IHttpAsyncHandler)this.innerApplication).EndProcessRequest(result);
        }

        #endregion

        #region IHttpHandler Members

        bool IHttpHandler.IsReusable { get { return ((IHttpHandler)this.innerApplication).IsReusable; } }

        void IHttpHandler.ProcessRequest(HttpContext context)
        {
            ((IHttpHandler)this.innerApplication).ProcessRequest(context);
        }

        #endregion
    }
}
